# -*- coding: utf-8 -*-
"""
华为云垃圾分类项目配置文件
集中管理项目的各种参数设置
"""

import os

class Config:
    """项目配置类"""
    
    # ==================== 基础配置 ====================
    # Python版本要求
    PYTHON_VERSION = "3.6"
    
    # 项目名称
    PROJECT_NAME = "huaweicloud_garbage_classify"
    
    # 项目版本
    VERSION = "1.0.0"
    
    # ==================== 模型配置 ====================
    # 支持的模型类型
    SUPPORTED_MODELS = {
        'resnet50': 'ResNet50',
        'vgg16': 'VGG16', 
        'senet50': 'SENet50'
    }
    
    # 默认模型
    DEFAULT_MODEL = 'resnet50'
    
    # 输入图像尺寸
    INPUT_SIZE = 224
    
    # 批次大小
    BATCH_SIZE = 64
    
    # 学习率
    LEARNING_RATE = 1e-3
    
    # 最大训练轮数
    MAX_EPOCHS = 40
    
    # 分类类别数
    NUM_CLASSES = 40
    
    # ==================== 数据处理配置 ====================
    # 数据格式
    DATA_FORMAT = {
        'image_extensions': ['.jpg', '.jpeg', '.png', '.bmp'],
        'label_format': '{image_name}.txt',
        'label_content_format': '{image_name}, {label_id}'
    }
    
    # 数据增强参数
    DATA_AUGMENTATION = {
        'center_crop': True,
        'random_crop': True,
        'crop_size': 224,
        'resize_size': 256,
        'label_smoothing': 0.05,
        'train_val_split': 0.1,  # 验证集比例
        'random_state': 0,       # 随机种子
        'shuffle': True          # 是否打乱数据
    }
    
    # 图像预处理参数
    IMAGE_PREPROCESSING = {
        'mean': [103.939, 116.779, 123.68],  # BGR均值
        'std': None,
        'mode': 'caffe'
    }
    
    # ==================== 训练配置 ====================
    # 损失函数
    LOSS_FUNCTIONS = {
        'categorical_crossentropy': '标准交叉熵损失',
        'arcface': 'ArcFace损失',
        'sphereface': 'SphereFace损失', 
        'cosface': 'CosFace损失',
        'normface': 'NormFace损失'
    }
    
    # 优化器
    OPTIMIZERS = {
        'adam': 'Adam优化器',
        'sgd': 'SGD优化器'
    }
    
    # 学习率衰减
    LEARNING_RATE_DECAY = 0.0005
    
    # 权重文件保留数量
    KEEP_WEIGHTS_FILE_NUM = 20
    
    # ==================== 评估配置 ====================
    # 评估指标
    EVALUATION_METRICS = ['accuracy']
    
    # 测试数据分割比例
    TEST_SPLIT_RATIO = 0.1
    
    # ==================== 部署配置 ====================
    # 模型保存格式
    MODEL_FORMATS = {
        'h5': 'Keras HDF5格式',
        'pb': 'TensorFlow SavedModel格式'
    }
    
    # 部署服务配置
    DEPLOYMENT_CONFIG = {
        'runtime': 'python3.6',
        'model_algorithm': 'image_classification',
        'model_type': 'TensorFlow'
    }
    
    # ==================== 路径配置 ====================
    # 训练数据目录
    TRAIN_DATA_DIR = 'datasets/garbage_classify/train_data'
    
    # 测试数据目录
    TEST_DATA_DIR = 'datasets/test_data'
    
    # 模型保存目录
    MODEL_DIR = 'model_snapshots'
    
    # 部署脚本目录
    DEPLOY_SCRIPTS_DIR = 'deploy_scripts'
    
    # 默认路径
    DEFAULT_PATHS = {
        'data_dir': TRAIN_DATA_DIR,
        'test_dir': TEST_DATA_DIR,
        'model_dir': MODEL_DIR,
        'deploy_scripts_dir': DEPLOY_SCRIPTS_DIR
    }
    
    # ==================== 垃圾分类类别配置 ====================
    # 垃圾类别映射
    GARBAGE_CATEGORIES = {
        # 其他垃圾 (0-5)
        0: "其他垃圾/一次性快餐盒",
        1: "其他垃圾/污损塑料", 
        2: "其他垃圾/烟蒂",
        3: "其他垃圾/牙签",
        4: "其他垃圾/破碎花盆及碟碗",
        5: "其他垃圾/竹筷",
        
        # 厨余垃圾 (6-13)
        6: "厨余垃圾/剩饭剩菜",
        7: "厨余垃圾/大骨头",
        8: "厨余垃圾/水果果皮",
        9: "厨余垃圾/水果果肉",
        10: "厨余垃圾/茶叶渣",
        11: "厨余垃圾/菜叶菜根",
        12: "厨余垃圾/蛋壳",
        13: "厨余垃圾/鱼骨",
        
        # 可回收物 (14-36)
        14: "可回收物/充电宝",
        15: "可回收物/包",
        16: "可回收物/化妆品瓶",
        17: "可回收物/塑料玩具",
        18: "可回收物/塑料碗盆",
        19: "可回收物/塑料衣架",
        20: "可回收物/快递纸袋",
        21: "可回收物/插头电线",
        22: "可回收物/旧衣服",
        23: "可回收物/易拉罐",
        24: "可回收物/枕头",
        25: "可回收物/毛绒玩具",
        26: "可回收物/洗发水瓶",
        27: "可回收物/玻璃杯",
        28: "可回收物/皮鞋",
        29: "可回收物/砧板",
        30: "可回收物/纸板箱",
        31: "可回收物/调料瓶",
        32: "可回收物/酒瓶",
        33: "可回收物/金属食品罐",
        34: "可回收物/锅",
        35: "可回收物/食用油桶",
        36: "可回收物/饮料瓶",
        
        # 有害垃圾 (37-39)
        37: "有害垃圾/干电池",
        38: "有害垃圾/软膏",
        39: "有害垃圾/过期药物"
    }
    
    # 垃圾大类
    GARBAGE_MAIN_CATEGORIES = {
        'other': '其他垃圾',
        'kitchen': '厨余垃圾', 
        'recyclable': '可回收物',
        'harmful': '有害垃圾'
    }
    
    # ==================== 环境配置 ====================
    # 依赖包版本
    DEPENDENCIES = {
        'tensorflow': '1.15.0',
        'keras': '2.3.1',
        'Pillow': '5.0.0',
        'numpy': '1.16.4',
        'scikit-learn': '0.21.3',
        # 'moxing': '1.17.0',  # 可选，仅用于华为云环境
        'opencv-python': '4.1.2.30',
        'matplotlib': '3.1.2',
        'h5py': '2.10.0'
    }
    
    # ==================== 工具方法 ====================
    @classmethod
    def get_category_name(cls, category_id):
        """根据类别ID获取类别名称"""
        return cls.GARBAGE_CATEGORIES.get(category_id, f"未知类别_{category_id}")
    
    @classmethod
    def get_main_category(cls, category_id):
        """根据类别ID获取大类名称"""
        if 0 <= category_id <= 5:
            return cls.GARBAGE_MAIN_CATEGORIES['other']
        elif 6 <= category_id <= 13:
            return cls.GARBAGE_MAIN_CATEGORIES['kitchen']
        elif 14 <= category_id <= 36:
            return cls.GARBAGE_MAIN_CATEGORIES['recyclable']
        elif 37 <= category_id <= 39:
            return cls.GARBAGE_MAIN_CATEGORIES['harmful']
        else:
            return "未知大类"
    
    @classmethod
    def validate_config(cls):
        """验证配置的有效性"""
        errors = []
        
        # 检查类别数量
        if len(cls.GARBAGE_CATEGORIES) != cls.NUM_CLASSES:
            errors.append(f"类别数量不匹配: 配置{cls.NUM_CLASSES}, 实际{len(cls.GARBAGE_CATEGORIES)}")
        
        # 检查输入尺寸
        if cls.INPUT_SIZE <= 0:
            errors.append("输入尺寸必须大于0")
        
        # 检查批次大小
        if cls.BATCH_SIZE <= 0:
            errors.append("批次大小必须大于0")
        
        return errors
    
    @classmethod
    def print_config(cls):
        """打印配置信息"""
        print("=" * 60)
        print(f"项目配置信息 - {cls.PROJECT_NAME} v{cls.VERSION}")
        print("=" * 60)
        print(f"Python版本要求: {cls.PYTHON_VERSION}")
        print(f"输入图像尺寸: {cls.INPUT_SIZE}x{cls.INPUT_SIZE}")
        print(f"批次大小: {cls.BATCH_SIZE}")
        print(f"学习率: {cls.LEARNING_RATE}")
        print(f"最大训练轮数: {cls.MAX_EPOCHS}")
        print(f"分类类别数: {cls.NUM_CLASSES}")
        print(f"默认模型: {cls.DEFAULT_MODEL}")
        print("=" * 60)
        print("数据生成器配置:")
        print(f"  图像预处理: {cls.DATA_AUGMENTATION['resize_size']}x{cls.DATA_AUGMENTATION['resize_size']} → {cls.DATA_AUGMENTATION['crop_size']}x{cls.DATA_AUGMENTATION['crop_size']}")
        print(f"  标签平滑: {cls.DATA_AUGMENTATION['label_smoothing']}")
        print(f"  验证集比例: {cls.DATA_AUGMENTATION['train_val_split']}")
        print(f"  随机种子: {cls.DATA_AUGMENTATION['random_state']}")
        print("=" * 60)
        
        # 验证配置
        errors = cls.validate_config()
        if errors:
            print("⚠️  配置验证警告:")
            for error in errors:
                print(f"   - {error}")
        else:
            print("✅ 配置验证通过")
        print("=" * 60)
    
    @classmethod
    def get_data_generator_info(cls):
        """获取数据生成器信息"""
        return {
            'preprocessing': {
                'resize_size': cls.DATA_AUGMENTATION['resize_size'],
                'crop_size': cls.DATA_AUGMENTATION['crop_size'],
                'label_smoothing': cls.DATA_AUGMENTATION['label_smoothing']
            },
            'augmentation': {
                'center_crop': cls.DATA_AUGMENTATION['center_crop'],
                'random_crop': cls.DATA_AUGMENTATION['random_crop'],
                'shuffle': cls.DATA_AUGMENTATION['shuffle']
            },
            'split': {
                'train_val_ratio': cls.DATA_AUGMENTATION['train_val_split'],
                'random_state': cls.DATA_AUGMENTATION['random_state']
            }
        }


# 创建全局配置实例
config = Config()

if __name__ == "__main__":
    # 打印配置信息
    config.print_config()
    
    # 测试类别映射
    print("\n类别映射测试:")
    for i in range(5):
        print(f"类别 {i}: {config.get_category_name(i)} -> {config.get_main_category(i)}") 